using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Xml.Serialization;
using log4net;
using Triton.Common.LogUtilities;

namespace Triton.Bot.Profiles
{
	[Serializable]
	[XmlRoot("Profile")]
	public class Profile : IAuthored
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class Class215
		{
			public static readonly Class215 Instance9 = new Class215();

			public static Func<PropertyInfo, bool> Instance9__26_0;

			internal bool method_0(PropertyInfo propertyInfo_0)
			{
				XmlAttributeAttribute customAttribute = propertyInfo_0.GetCustomAttribute<XmlAttributeAttribute>();
				if (customAttribute != null)
				{
					if (!(customAttribute.AttributeName == "RefTag") && !(customAttribute.AttributeName == "RefName"))
					{
						return true;
					}
					return false;
				}
				return propertyInfo_0.GetCustomAttributes<XmlElementAttribute>().Any();
			}
		}

		private readonly ILog _log = Logger.GetLoggerInstanceForType();

		private Dictionary<string, ProfileElement> _refList;

		public List<ProfileElement> Elements { get; internal set; }

		[XmlAttribute]
		public string Name { get; set; }

		[XmlAttribute]
		public string Description { get; set; }

		[XmlAttribute]
		public string Author { get; set; }

		[XmlAttribute]
		public string Version { get; set; }

		public Profile()
		{
			Elements = new List<ProfileElement>();
		}

		public ProfileElement FindReferenceElement(ProfileElement element)
		{
			if (element == null)
			{
				return null;
			}
			if (!string.IsNullOrEmpty(element.ReferenceTag))
			{
				ProfileElement profileElement = method_0(element.ReferenceTag);
				if (profileElement != null)
				{
					_log.Debug(string.Concat(element, " references ", profileElement.ReferenceTag));
				}
				if (profileElement != null)
				{
					element.ReferenceElement = profileElement;
				}
				return profileElement ?? element;
			}
			return element;
		}

		private ProfileElement method_0(string string_0)
		{
			if (_refList == null)
			{
				BuildReferences();
			}
			if (_refList.TryGetValue(string_0, out var value))
			{
				return value;
			}
			return null;
		}

		public void BuildReferences()
		{
			_refList = new Dictionary<string, ProfileElement>();
			foreach (ProfileElement element in Elements)
			{
				method_3(element);
			}
			foreach (ProfileElement element2 in Elements)
			{
				method_2(element2);
			}
		}

		private void method_1(ProfileElement profileElement_0, ProfileElement profileElement_1)
		{
			foreach (PropertyInfo item in profileElement_0.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(delegate(PropertyInfo propertyInfo_0)
			{
				XmlAttributeAttribute customAttribute2 = propertyInfo_0.GetCustomAttribute<XmlAttributeAttribute>();
				return (customAttribute2 != null) ? ((!(customAttribute2.AttributeName == "RefTag") && !(customAttribute2.AttributeName == "RefName")) ? true : false) : propertyInfo_0.GetCustomAttributes<XmlElementAttribute>().Any();
			}))
			{
				object obj = item.PropertyType.GetDefaultValue();
				DefaultValueAttribute customAttribute = item.GetCustomAttribute<DefaultValueAttribute>();
				if (customAttribute != null)
				{
					obj = customAttribute.Value;
				}
				object value = item.GetValue(profileElement_0);
				object value2 = item.GetValue(profileElement_1);
				if ((value2 == null || value2.Equals(obj)) && value != null && !value.Equals(obj) && (value2 == null || !value.Equals(value2)))
				{
					item.SetValue(profileElement_1, value);
				}
			}
		}

		private void method_2(ProfileElement profileElement_0)
		{
			if (!string.IsNullOrEmpty(profileElement_0.ReferenceTag))
			{
				ProfileElement profileElement = method_0(profileElement_0.ReferenceTag);
				if (profileElement != null)
				{
					profileElement_0.ReferenceElement = profileElement;
					method_1(profileElement, profileElement_0);
				}
			}
			if (!(profileElement_0 is ProfileGroupElement))
			{
				return;
			}
			foreach (ProfileElement child in (profileElement_0 as ProfileGroupElement).Children)
			{
				method_2(child);
			}
		}

		private void method_3(ProfileElement profileElement_0)
		{
			if (!string.IsNullOrEmpty(profileElement_0.ReferenceName))
			{
				if (_refList.ContainsKey(profileElement_0.ReferenceName))
				{
					throw new Exception("Profile already contains a reference element with name " + profileElement_0.ReferenceName + ". Cannot correctly load reference!");
				}
				_refList.Add(profileElement_0.ReferenceName, profileElement_0);
			}
			if (!(profileElement_0 is ProfileGroupElement))
			{
				return;
			}
			foreach (ProfileElement child in (profileElement_0 as ProfileGroupElement).Children)
			{
				method_3(child);
			}
		}
	}
}
